package com.haoxuer.discover.function.controller.rest;


import bsh.EvalError;
import bsh.Interpreter;
import com.haoxuer.discover.function.data.entity.Function;
import com.haoxuer.discover.function.data.service.FunctionService;
import com.haoxuer.discover.rest.base.ResponseObject;
import com.haoxuer.discover.web.controller.front.BaseController;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Scope;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;

@Scope("prototype")
@RestController
public class FunctionScripteRestController extends BaseController implements ApplicationContextAware {

    private ApplicationContext context;

    @Autowired
    private FunctionService functionService;

    @RequestMapping("/function_js/{key}")
    public ModelAndView function(@PathVariable("key") String key, HttpServletRequest request) {
        ModelAndView result = new ModelAndView(new MappingJackson2JsonView());

        Function function = functionService.findByKey(key);
        if (function == null) {

            result.addObject("code",501);
            result.addObject("msg","无效key");
            return result;
        }
        if (StringUtils.isEmpty(function.getScript())) {
            result.addObject("code",501);
            result.addObject("msg","无效脚本");
            return result;
        }

        Context cx = Context.enter();
        try {

            Scriptable scope = cx.initStandardObjects();
            Object wrappedOut = Context.javaToJS(System.out, scope);
            ScriptableObject.putProperty(scope, "out", wrappedOut);
            ScriptableObject.putProperty(scope, "context", Context.javaToJS(context, scope));
            ScriptableObject.putProperty(scope, "model", Context.javaToJS(result, scope));
            ScriptableObject.putProperty(scope, "request", Context.javaToJS(request, scope));

            cx.evaluateString(scope, function.getScript(), "<cmd>", 1, null);
        }catch (Exception e){
            result.addObject("code",501);
            result.addObject("msg",""+e.getMessage());
        }finally {
            Context.exit();
        }
        return result;
    }

    @RequestMapping("/api_js/{key}")
    public ModelAndView api(@PathVariable("key") String key, HttpServletRequest request) {
        ModelAndView result = new ModelAndView(new MappingJackson2JsonView());
        Function function = functionService.findByKey(key);
        if (function == null) {
            result.addObject("code", 501);
            result.addObject("msg", "无效key");
            return result;
        }
        if (StringUtils.isEmpty(function.getScript())) {
            result.addObject("code", 502);
            result.addObject("msg", "无效脚本");
            return result;
        }
      Context cx = Context.enter();
      try {

        Scriptable scope = cx.initStandardObjects();
        Object wrappedOut = Context.javaToJS(System.out, scope);
        ScriptableObject.putProperty(scope, "out", wrappedOut);
        ScriptableObject.putProperty(scope, "context", Context.javaToJS(context, scope));
        ScriptableObject.putProperty(scope, "request", Context.javaToJS(request, scope));
        ScriptableObject.putProperty(scope, "model", Context.javaToJS(result, scope));

        cx.evaluateString(scope, function.getScript(), "<cmd>", 1, null);
        Object back = scope.get("result", scope);
      } finally {
        Context.exit();
      }
        return result;
    }

    @RequestMapping("/page_js/{key}")
    public String page(@PathVariable("key") String key, HttpServletRequest request) {
        String result = "";
        Function function = functionService.findByKey(key);

        Interpreter interpreter = new Interpreter();
        try {
            interpreter.set("request", request);
            interpreter.set("context", context);

            if (function != null && function.getScript() != null) {
                StringBuffer buffer = new StringBuffer();
                buffer.append(function.getScript());
                interpreter.eval(buffer.toString());
            }
            Object object = interpreter.get("result");
            if (object != null) {
                if (object instanceof String) {
                    return getView((String) object);
                }
            }
        } catch (EvalError evalError) {
            evalError.printStackTrace();
        }
        return getView("nofound");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;

    }
}
